/**
 * Class: PColor
 *
 * Purpose: 
 *
 * Created: Jan 21, 2010 @ 11:11:09 AM
 * @author Ken Scott
 */
package org.openfantasia.ui;

import org.openfantasia.util.math.FPoint4;
import org.openfantasia.util.math.Math1D;
import org.openfantasia.util.math.PMath;

import java.awt.*;
import java.text.DecimalFormat;

public class PColor extends FPoint4 {

	public static final PColor NONE = null;

	public static final PColor INVISIBLE = new PColor(0, 0, 0, 0);

	public static final PColor WHITE = new PColor(1.0f, 1.0f, 1.0f, 1.0f);

	public static final PColor BLACK = new PColor(0f, 0f, 0f, 1.0f);

	public static final PColor LIGHT_GRAY = new PColor(0.75f, 0.75f, 0.75f, 1.0f);

	public static final PColor GRAY = new PColor(0.5f, 0.5f, 0.5f, 1.0f);

	public static final PColor DARK_GRAY = new PColor(0.25f, 0.25f, 0.25f, 1.0f);

	public static final PColor RED = new PColor(1.0f, 0f, 0f, 1.0f);

	public static final PColor MEDIUM_RED = RED.moreDarker();

	public static final PColor DARK_RED = MEDIUM_RED.moreDarker();

	public static final PColor GREEN = new PColor(0f, 1.0f, 0f, 1.0f);

	public static final PColor MEDIUM_GREEN = GREEN.moreDarker();

	public static final PColor DARK_GREEN = MEDIUM_GREEN.moreDarker();

	public static final PColor BLUE = new PColor(0f, 0f, 1.0f, 1.0f);

	public static final PColor MEDIUM_BLUE = BLUE.moreDarker();

	public static final PColor DARK_BLUE = MEDIUM_BLUE.moreDarker();

	public static final PColor CYAN = new PColor(0f, 1.0f, 1.0f, 1.0f);

	public static final PColor MAGENTA = new PColor(1.0f, 0f, 1.0f, 1.0f);

	public static final PColor YELLOW = new PColor(1.0f, 1.0f, 0f, 1.0f);

	public static final PColor ORANGE = new PColor(1.0f, .75f, 0f, 1.0f);


	public PColor() {
		super(1.0f, 1.0f, 1.0f, 1.0f);
	}


	public PColor(Color color) {
		super((float) color.getRed() / 255.0f, (float) color.getGreen() / 255.0f, (float) color.getBlue() / 255.0f, (float) color.getAlpha() / 255.0f);
	}


	public PColor(float red, float green, float blue) {
		super(red, green, blue, 1f);
	}


	public PColor(double red, double green, double blue) {
		this((float) red, (float) green, (float) blue, 1f);
	}


	public PColor(float red, float green, float blue, float alpha) {
		super(red, green, blue, alpha);
	}


	public PColor(double red, double green, double blue, double alpha) {
		super((float) red, (float) green, (float) blue, (float) alpha);
	}


	public PColor(float gray, float alpha) {
		super(gray, gray, gray, alpha);
	}


	public PColor(PColor that) {
		super(that);
	}


	public PColor copy() {
		return new PColor(this);
	}


	public void copy(PColor that) {
		p = Math1D.copy(that.p);
	}


	public static PColor random() {
		return new PColor(PMath.random(1f), PMath.random(1f), PMath.random(1f));
	}


	public static PColor random(double min, double max) {
		return new PColor(PMath.random(min, max), PMath.random(min, max), PMath.random(min, max));
	}


	public float getRed() {
		return p[0];
	}


	public float getGreen() {
		return p[1];
	}


	public float getBlue() {
		return p[2];
	}


	public float getAlpha() {
		return p[3];
	}


	public PColor brighter() {
		return scale(1.1f);
	}


	public PColor moreBrighter() {
		return scale(1.5f);
	}


	public PColor darker() {
		return scale(0.9f);
	}


	public PColor moreDarker() {
		return scale(0.5f);
	}


	public PColor moreOpaque() {
		return scale(1.0f, 1.1f);
	}


	public PColor moreTransparent() {
		return scale(1.0f, 0.9f);
	}


	public PColor opacify(float alpha) {
		PColor result = copy();
		result.p[3] = alpha;
		return result;
	}


	public PColor scale(float factor) {
		return new PColor(PMath.clip(0f, 1.0f, this.p[0] * factor), PMath.clip(0f, 1.0f, this.p[1] * factor), PMath.clip(0f, 1.0f, this.p[2] * factor), this.p[3]);
	}


	public PColor scale(float grayScale, float alphaScale) {
		return new PColor(PMath.clip(0f, 1.0f, this.p[0] * grayScale), PMath.clip(0f, 1.0f, this.p[1] * grayScale), PMath.clip(0f, 1.0f, this.p[2] * grayScale), PMath.clip(0f, 1.0f, this.p[3] * alphaScale));
	}


	public PColor scale(float redScale, float greenScale, float blueScale, float alphaScale) {
		return new PColor(PMath.clip(0f, 1.0f, this.p[0] * redScale), PMath.clip(0f, 1.0f, this.p[1] * greenScale), PMath.clip(0f, 1.0f, this.p[2] * blueScale), PMath.clip(0f, 1.0f, this.p[3] * alphaScale));
	}


	public Color toColor() {
		return new Color((int) (getRed() * 255.0), (int) (getGreen() * 255.0), (int) (getBlue() * 255.0));
	}


	public PColor fromColor(Color c) {
		p[0] = (float) c.getRed() / 255f;
		p[1] = (float) c.getGreen() / 255f;
		p[2] = (float) c.getBlue() / 255f;
		p[3] = (float) c.getAlpha() / 255f;
		return this;
	}


	public PColor fromHSB(float hue, float saturation, float brightness) {
		int rgb = Color.HSBtoRGB(hue, saturation, brightness);
		Color c = new Color(rgb);

		p[0] = (float) c.getRed() / 255f;
		p[1] = (float) c.getGreen() / 255f;
		p[2] = (float) c.getBlue() / 255f;
		p[3] = (float) 1;
		return this;
	}


	@Override
	public String toString() {
		StringBuilder result = new StringBuilder();

		DecimalFormat df = new DecimalFormat("#.###");
		result.append("PColor[");
		result.append("r=").append(df.format(p[0]));
		result.append(", g=").append(df.format(p[1]));
		result.append(", b=").append(df.format(p[2]));
		result.append(", a=").append(df.format(p[3]));
		result.append("]");

		return result.toString();
	}
}
